
#include "include.h"

extern char paTable[];
extern char paTableLen;

char txBuffer[4];
char rxBuffer[4];
unsigned int i = 0;

void readRFSettings() {
	char buf[48];
	char i;
	for (i = 0; i < sizeof(buf); ++i)
		buf[i] = TI_CC_SPIReadReg(i);
}

static void rfConfig() {
	/* Configuration for CC110L from SmartRF Studo */
	TI_CC_SPIWriteReg(TI_CCxxx0_IOCFG2, 0x2E);       //GDO2 Output Pin Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_IOCFG0, 0x06);       //GDO0 Output Pin Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_PKTCTRL0, 0x05);     //Packet Automation Control
	TI_CC_SPIWriteReg(TI_CCxxx0_FSCTRL1, 0x0C);      //Frequency Synthesizer Control
	TI_CC_SPIWriteReg(TI_CCxxx0_FREQ2, 0x21);        //Frequency Control Word, High Byte
	TI_CC_SPIWriteReg(TI_CCxxx0_FREQ1, 0x62);        //Frequency Control Word, Middle Byte
	TI_CC_SPIWriteReg(TI_CCxxx0_FREQ0, 0x76);        //Frequency Control Word, Low Byte
	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG4, 0x2D);      //Modem Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG3, 0x3B);      //Modem Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG2, 0x13);      //Modem Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_DEVIATN, 0x62);      //Modem Deviation Setting
	TI_CC_SPIWriteReg(TI_CCxxx0_MCSM1, 0x3F);        //Main Radio Control State Machine Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_MCSM0, 0x18);        //Main Radio Control State Machine Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_FOCCFG, 0x1D);       //Frequency Offset Compensation Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_BSCFG, 0x1C);        //Bit Synchronization Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL2, 0xC7);     //AGC Control
	TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL1, 0x00);     //AGC Control
	TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL0, 0xB0);     //AGC Control
	TI_CC_SPIWriteReg(TI_CCxxx0_WORCTRL, 0xFB);//Use setting from SmartRF Studio
	TI_CC_SPIWriteReg(TI_CCxxx0_FREND1, 0xB6);       //Front End RX Configuration
	TI_CC_SPIWriteReg(TI_CCxxx0_FSCAL3, 0xEA);       //Frequency Synthesizer Calibration
	TI_CC_SPIWriteReg(TI_CCxxx0_FSCAL2, 0x2A);       //Frequency Synthesizer Calibration
	TI_CC_SPIWriteReg(TI_CCxxx0_FSCAL1, 0x00);       //Frequency Synthesizer Calibration
	TI_CC_SPIWriteReg(TI_CCxxx0_FSCAL0, 0x1F);       //Frequency Synthesizer Calibration
	TI_CC_SPIWriteReg(TI_CCxxx0_TEST0, 0x09);        //Various Test Settings
}

#define CLOCK_HZ 16000000
#define HZ_US 1000000

void SPISetup(void) {
  // Configure the CSn GPIO.
  TI_CC_CSn_PxOUT |= TI_CC_CSn_PIN;
  TI_CC_CSn_PxDIR |= TI_CC_CSn_PIN;  // /CS disable

  UCB0CTL1 |= UCSWRST;

  UCB0CTL1 = UCSWRST | UCSSEL_2;  // SMCLK
  UCB0CTL0 = UCCKPL | UCMSB | UCMST | UCMODE_0 | UCSYNC;

  // The maximal allowed SPI clock rate without inserting
  // delays between address/data or burst bytes is 6.5 MHz.
  // SMCKL/3 is 5.3 MHz, which is as near as we'll get.
  UCB0BR0 = 3;   // UCLK/3
  UCB0BR1 = 0;

  // Configure the SIMO/SOMI/UCLK GPIOs for SPI.
  TI_CC_SPI_USCIB0_PxSEL |= TI_CC_SPI_USCIB0_SIMO
                         |  TI_CC_SPI_USCIB0_SOMI
                         |  TI_CC_SPI_USCIB0_UCLK;
  TI_CC_SPI_USCIB0_PxSEL2|= TI_CC_SPI_USCIB0_SIMO
                         |  TI_CC_SPI_USCIB0_SOMI
                         |  TI_CC_SPI_USCIB0_UCLK;

  // Turn on a pull-up for the SOMI pin for easier debugging.
  TI_CC_SPI_USCIB0_PxREN |= TI_CC_SPI_USCIB0_SOMI;
  TI_CC_SPI_USCIB0_PxOUT |= TI_CC_SPI_USCIB0_SOMI;

  UCB0CTL1 &= ~UCSWRST;  // **Initialize USCI state machine**
}

char SPIStrobe(char strobe) {
  TI_CC_CSn_PxOUT &= ~TI_CC_CSn_PIN;        // /CS enable
  while (!(IFG2&UCB0TXIFG))
	  ;                // Wait for TXBUF ready
  UCB0TXBUF = strobe;                       // Send strobe
  // Strobe addr is now being TX'ed
  while (UCB0STAT & UCBUSY)
	  ;                // Wait for TX to complete
  TI_CC_CSn_PxOUT |= TI_CC_CSn_PIN;         // /CS disable

  return UCB0RXBUF;  // Return status byte;
}

// The power up reset sequence is:
// Bring CS down for 20us and up for 20us.
// Bring CS down again, and wait for SO to go low.
// Send the SRES command strobe, and wait for SO to
// go low, signalling the end of reset.
char PowerupResetCC110L(void) {
  // /CSn down for 20us.
  TI_CC_CSn_PxOUT &= ~TI_CC_CSn_PIN;
  __delay_cycles(CLOCK_HZ/HZ_US*20);
  // /CSn up for 20us.
  TI_CC_CSn_PxOUT |= TI_CC_CSn_PIN;
  __delay_cycles(CLOCK_HZ/HZ_US*20);

  // CSn down again.
  TI_CC_CSn_PxOUT &= ~TI_CC_CSn_PIN;
  // Then wait for GDO1 to go low to signal RDY.
  while (TI_CC_GDO1_PxIN & TI_CC_GDO1_PIN)
	  ;

  while (!(IFG2&UCB0TXIFG))
	  ;                						// Wait for TXBUF ready
  UCB0TXBUF = TI_CCxxx0_SRES;               // Send strobe

  // Strobe addr is now being TX'ed
  while (UCB0STAT & UCBUSY)	                // Wait for TX to complete
	  ;

  // Wait for GDO1 to go low again to signal RDY.
  while (TI_CC_GDO1_PxIN & TI_CC_GDO1_PIN)
	  ;

  TI_CC_CSn_PxOUT |= TI_CC_CSn_PIN;         // /CS disable

  // Return the status byte.
  return UCB0RXBUF;
}

void main (void) {
  char status = 0;

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  /* Set the clock up for calibrated 16MHz RC oscillator. */
  BCSCTL2 = SELM_0 | DIVM_0 | DIVS_0;

  // Set the clock at 16MHz.
  if (CALBC1_16MHZ != 0xFF) {
      /* Adjust this accordingly to your VCC rise time */
      __delay_cycles(100000);

      /* Follow recommended flow. First, clear all DCOx and MODx bits. Then
       * apply new RSELx values. Finally, apply new DCOx and MODx bit values.
       */
      DCOCTL = 0x00;
      BCSCTL1 = CALBC1_16MHZ;     /* Set DCO to 16MHz */
      DCOCTL = CALDCO_16MHZ;
  }

  BCSCTL1 |= XT2OFF | DIVA_0;
  BCSCTL3 = XT2S_0 | LFXT1S_2 | XCAP_1;

  // Turn XIN/XOUT into GPIO.
  P2SEL = 0;
  P2SEL2 = 0;

  SPISetup();  // Initialize SPI port

  // P2SEL = 0;                                // Sets P2.6 & P2.7 as GPIO
  while ((TI_CC_SW_PxIN & TI_CC_SW1) == 0) {
	  status = PowerupResetCC110L();

	  // Start receiving.
	  SPIStrobe(TI_CCxxx0_SRX);

	  // Wait for 50 us.
	  __delay_cycles(CLOCK_HZ / HZ_US * 50);

	  // Power down for testing.
	  SPIStrobe(TI_CCxxx0_SIDLE);
	  SPIStrobe(TI_CCxxx0_SPWD);

	  // Wait for another 50 us.
	  __delay_cycles(CLOCK_HZ / HZ_US * 50);
  }

  // 10 ms delay.
  __delay_cycles(10000);

  rfConfig();  // Write RF settings to config reg

  TI_CC_SPIWriteBurstReg(TI_CCxxx0_PATABLE, paTable, paTableLen); //Write PATABLE

  // Configure ports -- switch inputs, LEDs, GDO0 to RX packet info from CCxxxx
  TI_CC_SW_PxREN = TI_CC_SW1;               // Enable Pull up resistor
  TI_CC_SW_PxOUT = TI_CC_SW1;               // Enable pull up resistor

  TI_CC_LED_PxOUT |= TI_CC_LED1; 			// Outputs = 1
  TI_CC_LED_PxDIR |= TI_CC_LED1;			// LED Direction to Outputs

  // Configure ports -- switch inputs, LEDs, GDO0 to RX packet info from CCxxxx
  TI_CC_SW_PxREN = TI_CC_SW1;               // Enable Pull up resistor
  TI_CC_SW_PxOUT = TI_CC_SW1;               // Enable pull up resistor
  TI_CC_SW_PxIES = TI_CC_SW1;               // Int on falling edge
  TI_CC_SW_PxIFG &= ~(TI_CC_SW1);           // Clr flags
  TI_CC_SW_PxIE = TI_CC_SW1;                // Activate interrupt enables
  TI_CC_LED_PxOUT |= TI_CC_LED1; 			// Outputs = 1
  TI_CC_LED_PxDIR |= TI_CC_LED1;			// LED Direction to Outputs

  TI_CC_GDO0_PxSEL &= ~TI_CC_GDO0_PIN;		//
  TI_CC_GDO0_PxIES |= TI_CC_GDO0_PIN;       // Int on falling edge (end of pkt)
  TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN;      // Clear interrupt flag
  TI_CC_GDO0_PxIE |= TI_CC_GDO0_PIN;        // Enable int on end of packet

  TI_CC_SPIStrobe(TI_CCxxx0_SRX);           // Initialize CCxxxx in RX mode.
                                            // When a pkt is received, it will
                                            // signal on GDO0 and wake CPU

  if ((TI_CC_SW_PxIN & TI_CC_SW1) == 0) {
	  int i = 0;
	  for (;; ++i) {
		// Build packet
		txBuffer[0] = status;
		txBuffer[0] = 2;                        // Packet length
		txBuffer[1] = 0x01;                     // Packet address
		txBuffer[2] = TI_CC_LED1;				// Toggle led1!
		RFSendPacket(txBuffer, 3);              // Send value over RF
		__delay_cycles(16000000/400);           // Switch debounce
	  }
  }
  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM3, enable interrupts
}


// The ISR assumes the interrupt came from a pressed button
#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR (void) {
  // If Switch was pressed
  if(TI_CC_SW_PxIFG & TI_CC_SW1)
  {
    // Build packet
    txBuffer[0] = 2;                        // Packet length
    txBuffer[1] = 0x01;                     // Packet address
    txBuffer[2] = TI_CC_LED1;				// Toggle led1!
    RFSendPacket(txBuffer, 3);              // Send value over RF
    __delay_cycles(5000);                   // Switch debounce
  }
  TI_CC_SW_PxIFG &= ~(TI_CC_SW1);           // Clr flag that caused int
}

// The ISR assumes the interrupt came from GDO0. GDO0 fires indicating that
// CCxxxx received a packet
#pragma vector=PORT2_VECTOR
__interrupt void Port2_ISR(void)
{
    // if GDO fired
  if(TI_CC_GDO0_PxIFG & TI_CC_GDO0_PIN)
  {
    char len=2;                             // Len of pkt to be RXed (only addr
                                            // plus data; size byte not incl b/c
                                            // stripped away within RX function)
    if (RFReceivePacket(rxBuffer,&len))     // Fetch packet from CCxxxx
    	TI_CC_LED_PxOUT ^= rxBuffer[1];     // Toggle LEDs according to pkt data
  }

  TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN;      // After pkt RX, this flag is set.
}
